package pl.edu.mimuw.irs.rcp.controller.editor.workflow.part;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.draw2d.Bendpoint;
import org.eclipse.draw2d.BendpointConnectionRouter;
import org.eclipse.draw2d.Connection;
import org.eclipse.draw2d.ConnectionAnchor;
import org.eclipse.draw2d.ConnectionEndpointLocator;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.PolygonDecoration;
import org.eclipse.draw2d.PolylineConnection;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.RelativeBendpoint;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.editparts.AbstractConnectionEditPart;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;

import pl.edu.mimuw.irs.core.model.petrinet.Arc;
import pl.edu.mimuw.irs.core.util.Position;
import pl.edu.mimuw.irs.core.util.RelativePosition;
import pl.edu.mimuw.irs.rcp.controller.editor.workflow.policy.ArcBendpointEditPolicy;
import pl.edu.mimuw.irs.rcp.controller.editor.workflow.policy.ArcEditPolicy;
import pl.edu.mimuw.irs.rcp.view.figure.ChopboxHandleBoundsAnchor;
import pl.edu.mimuw.irs.rcp.view.figure.EllipseHandleBoundsAnchor;

/**
 * @author Jakub Rauch
 * Created on: 2009-05-18
 */
public class ArcEditPart extends AbstractConnectionEditPart implements PropertyChangeListener {

	// *** Attributes

	// *** Methods
	
	@Override
	protected void refreshVisuals() {
		super.refreshVisuals();

		refreshBendpoints(getConnectionFigure());
	}
	
	@Override
	protected void createEditPolicies() {
		installEditPolicy(EditPolicy.CONNECTION_ROLE, new ArcEditPolicy());
		installEditPolicy(EditPolicy.CONNECTION_BENDPOINTS_ROLE, new ArcBendpointEditPolicy());
	}
	
	@Override
	public boolean isSelectable() {
		return true;
	}
	
	@Override
	public boolean isActive() {
		return true;
	}
	
	@Override
	protected ConnectionAnchor getSourceConnectionAnchor() {
		if (getSource() == null || !(getSource() instanceof INodeEditPart)) { 
			return super.getSourceConnectionAnchor();
		} else if (getSource() instanceof PlaceEditPart || 
				getSource() instanceof IRSPlaceEditPart) {
			return new EllipseHandleBoundsAnchor(((INodeEditPart)getSource()).getFigure());
		} else {
			return new ChopboxHandleBoundsAnchor(((INodeEditPart)getSource()).getFigure());
		}
	}
	
	@Override
	protected ConnectionAnchor getTargetConnectionAnchor() {
		if (getTarget() == null || !(getTarget() instanceof INodeEditPart)) { 
			return super.getTargetConnectionAnchor();
		} else if (getTarget() instanceof PlaceEditPart || 
				getTarget() instanceof IRSPlaceEditPart) {
			return new EllipseHandleBoundsAnchor(((INodeEditPart)getTarget()).getFigure());
		} else {
			return new ChopboxHandleBoundsAnchor(((INodeEditPart)getTarget()).getFigure());
		}
	}
	
	protected IFigure createFigure() {
		PolylineConnection connection = (PolylineConnection)super.createFigure();
		connection.setConnectionRouter(new BendpointConnectionRouter());
		connection.setTargetDecoration(new PolygonDecoration());
		
		// Anchors
		
		// Bendpoints
		refreshBendpoints(connection);
		
		// Labels
		int weight = getArc().getWeight();
		if (weight == 0) {
			connection.setForegroundColor(new Color(null, 180, 180, 180));
		} else if (weight == 1) {
		} else if (weight > 1) {
			Label label = new Label(new Integer(getArc().getWeight()).toString());
			Font placeFont = new Font(null, "Arial", 8, SWT.NORMAL);
	
			label.setFont(placeFont);
			label.setTextAlignment(PositionConstants.CENTER);
	        label.setTextPlacement(PositionConstants.CENTER);
	        
	        ConnectionEndpointLocator locator = 
	            new ConnectionEndpointLocator(connection, true);
	        locator.setUDistance(5);
	        locator.setVDistance(5);
	        
	        connection.add(label, locator);
		}
		return connection;
	}
	
	public Arc getArc() {
		return (Arc)getModel();
	}

	@Override
	public void activate() {
		super.activate();
		getArc().addPropertyChangeListener(this);
	}
	
	@Override
	public void deactivate() {
		super.deactivate();
		getArc().removePropertyChangeListener(this);
	}
	
	@Override
	public void propertyChange(PropertyChangeEvent event) {
		if (event.getPropertyName().equals(Arc.VERTICES)) {
			/*
			 * Reload Vertices
			 */
			refreshBendpoints(getConnectionFigure());
		}
	}

	private void refreshBendpoints(Connection connection) {
		List<RelativePosition> vertices = (List<RelativePosition>) getArc().getVertices();
		List<Bendpoint> bendpoints = new ArrayList<Bendpoint>(vertices.size() * 2);
		for (RelativePosition vertex : vertices) {
			RelativeBendpoint bendpoint = new RelativeBendpoint(connection);
			Position rel1 = vertex.getRel1();
			Position rel2 = vertex.getRel2();
			Dimension dim1 = new Dimension(rel1.getX(), rel1.getY());
			Dimension dim2 = new Dimension(rel2.getX(), rel2.getY());
			bendpoint.setRelativeDimensions(dim1, dim2);
			bendpoints.add(bendpoint);
		}
		connection.setRoutingConstraint(bendpoints);
	}
}
